from django.urls import path, reverse
from django.forms import modelformset_factory

from oracle.base.baseview import render_handler
from oracle.base.tools import get_random_string
from gideon.service.starlabs import GideonHandler, custom_handler_view_init
from supergirl.models import ClassList, CourseRecord, StudyRecord
from supergirl.forms.courserecordforms import StudyRecordModelForm


class CourseRecordHandler(GideonHandler):
    display_list = ["checkbox", "class_object", "day_num", "teacher", "date", "attendance"]
    action_list = ["init"]

    def action_multi_init(self, title=False, data=None, url=None, *args, **kwargs):
        if data is None:
            data = dict()
        if title:
            return '批量初始化考勤'
        else:
            # 获取上课记录key列表
            course_record_key_list = self.request.POST.getlist('key')
            class_key = kwargs.get("class_key")
            # 获取班级实例
            class_object = ClassList.objects.filter(key=class_key).first()
            url = self.reverse_url_list(request=self.request, class_key=class_key)
            if not class_object:
                status = "select_object_not_exist"
                data.update(
                    {
                        "head_title": "班级不存在",
                        "title": "班级不存在",
                        "href": url,
                        "button_text": "返回列表页"
                    }
                )
            else:
                # 但前班级所有的学生信息
                student_list = class_object.student_set.all()
                for course_record_key in course_record_key_list:
                    course_record_object = CourseRecord.objects.filter(key=course_record_key,
                                                                       class_object=class_object).first()
                    # 上课记录如果不存在
                    if not course_record_object:
                        continue
                    # 考勤记录是否已经存在
                    study_record = StudyRecord.objects.filter(course_record=course_record_object)
                    if study_record:
                        continue
                    # 为每个学生创建考勤记录
                    # for stu in student_list:
                    #     StudyRecord.objects.create(student=stu, course_record=course_record_object)
                    study_record_list = list()
                    key_list = list()
                    for stu in student_list:
                        # TODO 性能问题
                        # 确保获取的key唯一
                        while True:
                            key = get_random_string(24)
                            if not StudyRecord.objects.filter(key=key).exists() and key not in key_list:
                                key_list.append(key)
                                break
                        study_record_list.append(StudyRecord(key=key, student=stu, course_record=course_record_object))
                    StudyRecord.objects.bulk_create(study_record_list, batch_size=50)
                status = "success"
                data.update(
                    {
                        "head_title": "批量初始化成功",
                        "title": "班级学生批量初始化考勤记录成功",
                        "href": url,
                        "button_text": "返回列表页"
                    }
                )
        return status

    @custom_handler_view_init("attendance")
    def attendance_view(self, request, data, handler_view_type, *args, **kwargs):
        """
        考勤的批量操作
        :param request:
        :param data: 操作数据，由装饰器传入。所有数据都要注入data中，以便装饰器返回render方法时能获取到数据进行渲染
        :param handler_view_type: 视图操作类型，由装饰器传入。如果不主动指定这两个参数可以通过kwargs.get("data")/kwargs.get("handler_view_type")获取
        :param args:
        :param kwargs:
        :return: 返回dict类型数据，字典内容如下，没有对应的key会有默认值
            {
                "status": status,
                "method": None,
                "template": None,
                "msg": None,
                "args": args,
                "kwargs": kwargs
            }
        """
        status = "success"
        template = None
        course_record_key = kwargs.get("key")
        study_record_list = StudyRecord.objects.filter(course_record_id=course_record_key)
        if study_record_list:
            study_model_formset = modelformset_factory(StudyRecord, form=StudyRecordModelForm, extra=0)
            # formset = study_model_formset(queryset=study_record_list)
            # # 后期如果扩展前后端分离并且需要formset提供后端格式化数据，变量如下：
            # for form in formset:
            #     # 获取字段名
            #     # ['student', 'record', 'id']
            #     print(list(form.fields.keys()))
            #     # 获取实例数值
            #     # 获取主键
            #     # 3 <class 'int'>
            #     print(form.instance.id, type(form.instance.id))
            #     # # 3 <class 'int'>
            #     print(form.instance.pk, type(form.instance.pk))
            #     # Python全栈(2期) day3 <class 'supergirl.models.CourseRecord'>
            #     print(form.instance.course_record, type(form.instance.course_record))
            #     # 因为已经定义外键关联字段为key，所以 course_record_id 查找值为字符串
            #     # SrRo2Nq3OQPgCj9h6sacwXIU <class 'str'>
            #     print(form.instance.course_record_id, type(form.instance.course_record_id))
            #     # 时间对象类型
            #     # 16:24:09.517600 <class 'datetime.time'>
            #     print(form.instance.create_time, type(form.instance.create_time))
            #     # jkHr3ZACTvSXUF2pu8hBzbVy <class 'str'>
            #     print(form.instance.key, type(form.instance.key))
            #     # 可选类型有 get_record_display 方法，使用方法为 form.instance.get_record_display()
            #     # checked <class 'str'>
            #     print(form.instance.record, type(form.instance.record))
            #     # record字段的选项
            #     # (('checked', '已签到'), ('vacate', '请假'), ('late', '迟到'), ('noshow', '缺勤'), ('leave_early', '早退')) <class 'tuple'>
            #     print(form.instance.record_choices, type(form.instance.record_choices))
            #     # superman <class 'supergirl.models.Student'>
            #     print(form.instance.student, type(form.instance.student))
            #     # q2 <class 'str'>
            #     print(form.instance.student_id, type(form.instance.student_id))
            #     # 单独构建表单时需要由js拼接传回， 拼接字段类似于 form-0-record form-0-student
            #     # form-0 <class 'str'>
            #     print(form.prefix, type(form.prefix))
            #     #  <class 'django.forms.utils.ErrorDict'>
            #     print(form.errors, type(form.errors))
            #     # {'student': 'q2', 'record': 'checked'} <class 'dict'>
            #     print(form.initial, type(form.initial))
            #     # ['student', 'record', 'id'] <class 'list'>
            #     print(form.changed_data, type(form.changed_data))
            if request.method == "POST":
                formset = study_model_formset(queryset=study_record_list, data=request.POST)
                if formset.is_valid():
                    formset.save()
                else:
                    template = "supergirl/attendance.html"
            else:
                formset = study_model_formset(queryset=study_record_list)
                template = "supergirl/attendance.html"
            data["formset"] = formset
        else:
            data.update({
                "head_title": "没有学生考勤记录",
                "title": "没有学生考勤记录，请初始化考勤记录或者确定原因后重试",
            })
            template = "supergirl/attendance.html"
        data.update(self.get_context_data(*args, **kwargs))

        # TODO 没有判断前后端渲染
        return {"status": status, "template": template, "args": args, "kwargs": kwargs}

    def get_queryset(self, handle_type='list', *args, **kwargs):
        class_key = kwargs.get("class_key", "")
        if handle_type == "list":
            return self.model_class.objects.filter(class_object__key=class_key)
        else:
            return self.model_class.objects.filter(class_object__key=class_key).first()

    def get_urls(self):
        patterns = [
            # 可以使用面板或者时间树的形式进行展示
            path(r'list/<slug:class_key>/', self.handler_view_list, name=self.get_url_name_list()),
            path(r'add/<slug:class_key>/', self.handler_view_add, name=self.get_url_name_add()),
            path(r'change/<slug:key>/<slug:class_key>/', self.handler_view_change, name=self.get_url_name_change()),
            path(r'delete/<slug:key>/<slug:class_key>/', self.handler_view_delete, name=self.get_url_name_delete()),
            # 查看学生考勤记录的url
            path(r'attendance/<slug:key>/<slug:class_key>/', self.attendance_view,
                 name=self.get_url_name_add("attendance")),
        ]
        patterns.extend(self.get_extra_urls())

        return patterns

    def reverse_url_add(self, request, *args, **kwargs):
        """
        生成带原搜索条件的添加url
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        class_key = kwargs.get("class_key", "")
        return self.reverse_handle_url(request, self.get_url_name_add(), class_key=class_key)

    def reverse_url_change(self, request, obj, *args, **kwargs):
        """
        生成带原搜索条件的修改url
        :param request:
        :param obj:
        :param args:
        :param kwargs:
        :return:
        """
        class_key = kwargs.get("class_key", "")
        key = obj.key
        return self.reverse_handle_url(request, self.get_url_name_change(), key=key, class_key=class_key)

    def reverse_url_delete(self, request, obj, *args, **kwargs):
        """
        生成带原搜索条件的删除url
        :param request:
        :param args:
        :param obj:
        :param kwargs:
        :return:
        """
        class_key = kwargs.get("class_key", "")
        key = obj.key
        return self.reverse_handle_url(request, self.get_url_name_delete(), key=key, class_key=class_key)

    def reverse_url_list(self, request, *args, **kwargs):
        """
        跳转回页面时生成的url
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        class_key = kwargs.get("class_key", "")
        name = f'{self.site.namespace}:{self.get_url_name_list()}'
        list_url = reverse(name, kwargs={"class_key": class_key, })
        params = request.GET.get('_filter')
        if params:
            list_url = f'{list_url}?{params}'
        return list_url

    def saving_pre_handler(self, form, is_update=False, *args, **kwargs):
        class_key = kwargs.get("class_key", "")
        if not is_update:
            form.instance.class_object_id = class_key
        return True

    def show_date_field(self, obj=None, is_title=False, *args, **kwargs):
        time_format = '%Y-%m-%d %H:%M:%S'
        return self.format_datetime_field(obj, "date", is_title=is_title, time_format=time_format)

    def show_attendance_field(self, obj=None, is_title=False, *args, **kwargs):
        """
        显示学生考勤记录的按钮
        :param obj: model object
        :param is_title: 是否显示标题标志
        :param args:
        :param kwargs:
        :return:
        """
        title = "考勤"
        if is_title:
            return title
        if obj:
            class_key = kwargs.get("class_key")
            url = self.reverse_handle_url(self.request, self.get_url_name_add("attendance"), key=obj.key,
                                          class_key=class_key)
            return {"href": url, "title": title}, "body", {"type": "link", "target": "_blank"}
        return "attendance record function error"
